[アップデート]AWS SAM CLIのTerraform統合利用時にモジュール等を別フォルダに配置できるようになりました
初めに
先日しばらく更新が止まっていたAWS SAM CLIのv1.96.0がリリースされました。今回はTerraform周りの方が触られているような印象があります。
SAMでのTerraform統合のビルドの仕様として実行時のディレクトリではなく一時的に別の場所にファイルを複製しそれを元に処理が行われますが、この複製されるファイル群はsam build
を実行したディレクトリ配下のもののみとなるためそれ以外のパスに参照するファイルがあるとビルドができない問題を抱えていたようです
例えば以下の構成の場合大元のmain.tf
をdev
ディレクトリにおいてしまってるのでその外側のmodules
やlambdaで利用するアプリコードがビルド時に参照できないものとなります(ハイライト部分のみが対象となる)。
$ tree sam-app-terraform/ . ├── hello_world ## lambdaのアプリコード(terraformの構成とは関係ない) │ ├── __init__.py │ └── app.py └── terraform ## ここ配下がterraform関連のファイル ├── environments │ └── dev │ ├── main.tf ## これが大元のtfファイル │ └── samconfig.toml └── modules └── hello_world └── main.tf
今回のバージョンで追加された--terraform-project-root-path
オプションを適切に指定することで今後はこの構成が採用可能となり、Terraformらしいディレクトリ構成の利用やインフラとアプリコードのディレクトリの分離をすることができます。
何が問題だった
例えば先ほどの構造でdev/main.tf
のファイル内容を以下のように記載しsam build --hook-name terraform
を実行してビルドを施行するとmodule
で指定されたパスの解決ができずに内部的に実行されるterrafrom
コマンドの実行が失敗します。
provider "aws" { profile = "default" region = "ap-northeast-1" } module "hello_world_function" { source = "../../modules/hello_world" }
$ sam build --hook-name terraform ... │ Error: Unreadable module directory │ │ Unable to evaluate directory symlink: lstat ../../modules: no such file or │ directory ╵ ...
先ほどの構造を考えると本来は問題なく読み込まれるはずですが、SAMではビルド時の処理として一旦別の場所に処理するファイルをコピーしてそこで必要な処理を行うようになっています。
そのコピーされるファイルについてですがsam build
を実行した際ディレクトリ配下のもののみとなるためdev
配下外に設置されるものは対象外となります。
実際に--debug
オプションをつけて作業用のファイルのコピーフェーズを確認してみるとdev
配下のファイルのみがコピーされておりそれ以外のものは処理されていないことが確認できます。
023-09-05 22:16:34,116 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/terraform.tfstate) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/terraform.tfstate) 2023-09-05 22:16:34,116 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/main.tf) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/main.tf) 2023-09-05 22:16:34,117 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/z_samcli_backend_override.tf) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/z_samcli_backend_override.tf) 2023-09-05 22:16:34,118 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/9fda4126-74f0-4015-8432-f62f2c671d41.tfstate) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/9fda4126-74f0-4015-8432-f62f2c671d41.tfstate) 2023-09-05 22:16:34,118 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform 2023-09-05 22:16:34,118 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform) 2023-09-05 22:16:34,119 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/terraform.tfstate) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/terraform.tfstate) 2023-09-05 22:16:34,120 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers 2023-09-05 22:16:34,120 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/providers) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers) 2023-09-05 22:16:34,121 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io 2023-09-05 22:16:34,121 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/providers/registry.terraform.io) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io) 2023-09-05 22:16:34,121 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp 2023-09-05 22:16:34,122 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/providers/registry.terraform.io/hashicorp) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp) 2023-09-05 22:16:34,122 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/null 2023-09-05 22:16:34,123 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/providers/registry.terraform.io/hashicorp/null) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/null) 2023-09-05 22:16:34,123 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/null/3.2.1 2023-09-05 22:16:34,123 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/providers/registry.terraform.io/hashicorp/null/3.2.1) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/null/3.2.1) 2023-09-05 22:16:34,124 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/null/3.2.1/darwin_arm64 2023-09-05 22:16:34,124 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/providers/registry.terraform.io/hashicorp/null/3.2.1/darwin_arm64) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/null/3.2.1/darwin_arm64) 2023-09-05 22:16:34,126 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/providers/registry.terraform.io/hashicorp/null/3.2.1/darwin_arm64/terraform-provider-null_v3.2.1_x5) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/null/3.2.1/darwin_arm64/terraform-provider-null_v3.2.1_x5) 2023-09-05 22:16:34,131 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/aws 2023-09-05 22:16:34,131 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/providers/registry.terraform.io/hashicorp/aws) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/aws) 2023-09-05 22:16:34,132 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/aws/5.15.0 2023-09-05 22:16:34,132 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/providers/registry.terraform.io/hashicorp/aws/5.15.0) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/aws/5.15.0) 2023-09-05 22:16:34,133 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/aws/5.15.0/darwin_arm64 2023-09-05 22:16:34,133 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/providers/registry.terraform.io/hashicorp/aws/5.15.0/darwin_arm64) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/aws/5.15.0/darwin_arm64) 2023-09-05 22:16:34,134 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/providers/registry.terraform.io/hashicorp/aws/5.15.0/darwin_arm64/terraform-provider-aws_v5.15.0_x5) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/providers/registry.terraform.io/hashicorp/aws/5.15.0/darwin_arm64/terraform-provider-aws_v5.15.0_x5) 2023-09-05 22:16:34,235 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/modules 2023-09-05 22:16:34,235 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/modules) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/modules) 2023-09-05 22:16:34,240 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform/modules/modules.json) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform/modules/modules.json) 2023-09-05 22:16:34,241 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/samconfig.toml) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/samconfig.toml) 2023-09-05 22:16:34,241 | File (.aws-sam) is in ignored set, skipping it 2023-09-05 22:16:34,242 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.aws-sam-iacs 2023-09-05 22:16:34,242 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.aws-sam-iacs) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.aws-sam-iacs) 2023-09-05 22:16:34,243 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.aws-sam-iacs/iacs_metadata 2023-09-05 22:16:34,243 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.aws-sam-iacs/iacs_metadata) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.aws-sam-iacs/iacs_metadata) 2023-09-05 22:16:34,244 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.aws-sam-iacs/iacs_metadata/template.json) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.aws-sam-iacs/iacs_metadata/template.json) 2023-09-05 22:16:34,244 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.aws-sam-iacs/iacs_metadata/Makefile) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.aws-sam-iacs/iacs_metadata/Makefile) 2023-09-05 22:16:34,245 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.aws-sam-iacs/iacs_metadata/copy_terraform_built_artifacts.py) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.aws-sam-iacs/iacs_metadata/copy_terraform_built_artifacts.py) 2023-09-05 22:16:34,245 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.aws-sam-iacs/iacs_metadata/__pycache__ 2023-09-05 22:16:34,246 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.aws-sam-iacs/iacs_metadata/__pycache__) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.aws-sam-iacs/iacs_metadata/__pycache__) 2023-09-05 22:16:34,246 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.aws-sam-iacs/iacs_metadata/__pycache__/zip.cpython-311.pyc) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.aws-sam-iacs/iacs_metadata/__pycache__/zip.cpython-311.pyc) 2023-09-05 22:16:34,248 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.aws-sam-iacs/iacs_metadata/zip.py) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.aws-sam-iacs/iacs_metadata/zip.py) 2023-09-05 22:16:34,249 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.aws-sam-iacs/iacs_metadata/z_samcli_backend_override) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.aws-sam-iacs/iacs_metadata/z_samcli_backend_override) 2023-09-05 22:16:34,250 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/environments/dev/.terraform.lock.hcl) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/.terraform.lock.hcl)
そのため環境を分けるためには別の分割方法とするか、main.tfが置いてあるディレクトリ配下にシンボリックリンクを貼るなどして利用するファイルをすべて実行ディレクトリ配下に収める構成を検討する必要がありました。
追加されたオプション
今回追加された--terraform-project-root-path
をしていることで処理時の大元のパスを変更できるようになり、先に記載したディレクトリ構成が利用可能となりました。
今回の場合は--terraform-project-root-path ../../../
を指定してdev
直下でで実行すると、sam-app-terraform
を起点としてファイルが作業用ディレクトリにコピーされるようになるのでビルドに成功するようになります。
# dev配下で実行 $ sam build --hook-name terraform --terraform-project-root-path ../../../ ... Build Succeeded Built Artifacts : .aws-sam/build Built Template : .aws-sam/build/template.yaml Commands you can use next ========================= [*] Invoke Function: sam local invoke --hook-name terraform [*] Emulate local Lambda functions: sam local start-lambda --hook-name terraform ## 必要なファイルがビルドアーティファクトの格納先に設置されている $ tree .aws-sam .aws-sam ├── build │ ├── ModuleHelloWorldFunctionAwsLambdaFunctionHelloWorldCD3E0E1F │ │ ├── main.tf │ │ └── src │ │ ├── __init__.py │ │ ├── app.py │ │ └── requirements.txt │ └── template.yaml
--debug
をつけて実行してみると先ほどまでなかったmodules配下のファイルが追加されており、コピー先のパスもdev
からの相対パスだったのが(ex. /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpxd74p0v5/main.tf)
)aws-sam-terraform
直下からの相対パスになっています(ex. /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpbz_ghgt3/terraform/modules/hello_world/main.tf
)。
... 2023-09-05 23:13:40,081 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/modules/hello_world/main.tf) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpbz_ghgt3/terraform/modules/hello_world/main.tf) 2023-09-05 23:13:40,082 | Creating target folders at /var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpbz_ghgt3/terraform/modules/hello_world/src 2023-09-05 23:13:40,082 | Copying directory metadata from source (/Users/xxxx/sam-app-terraform/terraform/modules/hello_world/src) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpbz_ghgt3/terraform/modules/hello_world/src) 2023-09-05 23:13:40,083 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/modules/hello_world/src/requirements.txt) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpbz_ghgt3/terraform/modules/hello_world/src/requirements.txt) 2023-09-05 23:13:40,084 | Copying source file (/Users/xxxx/sam-app-terraform/terraform/modules/hello_world/src/__init__.py) to destination (/var/folders/8m/b717gxmx46l7ytmt2smb507w0000gp/T/tmpbz_ghgt3/terraform/modules/hello_world/src/__init__.py) ...
終わりに
今回のアップデートはterrafomr側の制約が大きく緩和れれたのみだけではなく、インフラとアプリのコードのディレクトリの分離もできるようになったので地味ながら人によっては大きなアップデートではないでしょうか。
(見ようによってはバグと捉える方もいるかもしれませんが取り扱いとしては新機能(type/feat
)のようです)。
余談ですが今回実はこの件と関係ないところで結構ハマりましてsam_metadata_xxx
を指定しないと関数のビルドがされず、かつ明確な記載はないのですがマネージドランタイム系のものを使っても標準のビルドが走らなず(Pythonの場合はpipが走らなかった、ログ等からおそらく仕様?)、なぜか動かない想定の構造でアプリが動く、動くはずの想定でなぜか動かないを繰り返していました。
ビルドは成功するけどアプリの挙動が何か怪しいなーと思ったらでフィルとでは.aws-sam/build
配下がビルドアーティファクト出力先となるのでこちらを確認してみてください。